#pragma once
#include<iostream>
#include<string>
#include<assert.h>
using namespace std;
namespace ly
{
	template<class T1,class T2>
	class vector_iterator
	{
		//typedef iterator<T> iterator;
	public:
		vector_iterator(T1 x) : _it(x) {}
		vector_iterator operator++(int){
			vector_iterator tmp = *this;
			_it++;
			return tmp;
		}
		vector_iterator operator++(){
			_it++;
			return *this;
		}
		vector_iterator operator--(int){
			iterator tmp(this->_it);
			_it--;
			return tmp;
		}
		vector_iterator operator--(){
			return --_it;
		}
		T2 operator*(){	return *_it;	}
		T2 operator->() {
			return *_it;
		}
		bool operator!=(vector_iterator x){
			return (x._it) != (this->_it);
		}
	private:
		T1 _it;
	};
	//template<class T>
	//class const_iterator
	//{
	//	//typedef const_iterator<T> const_iterator;
	//public:
	//	const_iterator(T* x) : _it(x) {}
	//	const_iterator operator++(int) {
	//		const_iterator tmp = *this;
	//		_it++;
	//		return tmp;
	//	}
	//	const_iterator operator++() {
	//		_it++;
	//		return *this;
	//	}
	//	const_iterator operator--(int){
	//		const_iterator tmp(*this->_it);
	//		_it--;
	//		return tmp;
	//	}
	//	const_iterator operator--(){
	//		return --_it;
	//	}
	//	T operator*() { return *_it; }
	//	bool operator!=(const_iterator x){
	//		return (x._it) != (this->_it);
	//	}
	//private:
	//	const T* _it;
	//};
	template<class T>
	class vector
	{
		friend ostream& operator<<(ostream& out, vector<T> x);
	public:
		typedef vector_iterator<T*,T> iterator;
		typedef vector_iterator<const T*,T> const_iterator;
		vector(size_t n = 0,T x=T())
		{

			if (n == 0) {
				_nums = nullptr;
				_size = _capacity = 0;
			}
			else {
				_nums = new T[n];
				for (int i = 0; i < n; ++i)
					_nums[i] = x;
				_size = n;
				_capacity = n;
			}
		}
		/*vector(size_t n=0,string x="")
		{
			_nums = new T[n];
			_size = n;
			_capacity = n;
		}*/
		vector(const vector<T>& x)
		{
			int i = 0; _size = x._size;
			_nums = new T[_size];
			_capacity = x._capacity;
			if (_size == 0);
			else {
				for (auto e : x) {
					_nums[i] = e;
					i++;
				}
			}
		}
		~vector()
		{
			delete[] _nums;
			_size = 0;
			_capacity = 0;
		}
		T& operator[](size_t i)
		{
			assert(i < _size);
			return _nums[i];
		}
		const T& operator[](size_t i) const{
			assert(i < _size);
			return _nums[i];
		}
		iterator begin(){
			iterator tmp(_nums);
			return tmp;
			//return _nums;
		}
		iterator end() {
			iterator tmp(_nums + _size);
			return tmp;
			//return _nums + _size;
		}
		const_iterator begin() const{	return _nums;	}
		const_iterator end() const{
			const_iterator tmp(_nums + _size);
			return tmp;
			//return (_nums + _size);
		}
		vector<T>& operator=(const vector<T>& x)
		{
			vector<T> tmp(x);
			swap(*this, tmp);
			return *this;
		}
		void push_back(T data)
		{
			if (_size == _capacity)
			{
				T* tmp = new T[2 * _capacity];
				assert(tmp);
				for (int i= 0; i < _size; i++){
					tmp[i] = _nums[i];
				}
				tmp[_size++] = data;
				delete[] _nums; _nums = tmp; _capacity *= 2;
			}
			else{	_nums[_size++] = data;	}
		}
		void pop_back(){	_size--;	}
		T back(){
			assert(_size != 0);
			return _nums[_size - 1];
		}
		size_t size(){	return _size;	}
		size_t capacity()	{	return _capacity;	}
	private:
		T* _nums;
		size_t _size;
		size_t _capacity;
	};
	/*template<class T>
	void swap(vector<T>& x,vector<T>& y )
	{
		
	}*/
	template<class T>
	ostream& operator<<(ostream& out,vector<T> x)
	{
		for (int i = 0; i < x._size; ++i)
			cout << x[i];
		return out;
	}
}